/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.examples.datagrid.store.spring;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.cache.Cache;
import javax.cache.integration.CacheLoaderException;
import javax.sql.DataSource;
import org.apache.ignite.IgniteException;
import org.apache.ignite.cache.store.CacheStore;
import org.apache.ignite.cache.store.CacheStoreAdapter;
import org.apache.ignite.examples.model.Person;
import org.apache.ignite.lang.IgniteBiInClosure;
import org.h2.jdbcx.JdbcConnectionPool;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
/**
* Example of {@link CacheStore} implementation that uses JDBC
* transaction with cache transactions and maps {@link Long} to {@link Person}.
*/
public class CacheSpringPersonStore extends CacheStoreAdapter<Long, Person> {
/** Data source. */
public static final DataSource DATA_SRC =
JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", "");
/** Spring JDBC template. */
private JdbcTemplate jdbcTemplate;
/**
* Constructor.
*
* @throws IgniteException If failed.
*/
public CacheSpringPersonStore() throws IgniteException {
jdbcTemplate = new JdbcTemplate(DATA_SRC);
}
/** {@inheritDoc} */
@Override public Person load(Long key) {
System.out.println(">>> Store load [key=" + key + ']');
try {
return jdbcTemplate.queryForObject("select * from PERSON where id = ?", new RowMapper<Person>() {
@Override public Person mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Person(rs.getLong(1), rs.getString(2), rs.getString(3));
}
}, key);
}
catch (EmptyResultDataAccessException ignored) {
return null;
}
}
/** {@inheritDoc} */
@Override public void write(Cache.Entry<? extends Long, ? extends Person> entry) {
Long key = entry.getKey();
Person val = entry.getValue();
System.out.println(">>> Store write [key=" + key + ", val=" + val + ']');
int updated = jdbcTemplate.update("update PERSON set first_name = ?, last_name = ? where id = ?",
val.firstName, val.lastName, val.id);
if (updated == 0) {
jdbcTemplate.update("insert into PERSON (id, first_name, last_name) values (?, ?, ?)",
val.id, val.firstName, val.lastName);
}
}
/** {@inheritDoc} */
@Override public void delete(Object key) {
System.out.println(">>> Store delete [key=" + key + ']');
jdbcTemplate.update("delete from PERSON where id = ?", key);
}
/** {@inheritDoc} */
@Override public void loadCache(final IgniteBiInClosure<Long, Person> clo, Object... args) {
if (args == null || args.length == 0 || args[0] == null)
throw new CacheLoaderException("Expected entry count parameter is not provided.");
int entryCnt = (Integer)args[0];
final AtomicInteger cnt = new AtomicInteger();
jdbcTemplate.query("select * from PERSON limit ?", new RowCallbackHandler() {
@Override public void processRow(ResultSet rs) throws SQLException {
Person person = new Person(rs.getLong(1), rs.getString(2), rs.getString(3));
clo.apply(person.id, person);
cnt.incrementAndGet();
}
}, entryCnt);
System.out.println(">>> Loaded " + cnt + " values into cache.");
}
}